<?php

namespace App\Models\Account;

use App\Models\BaseModel;
use App\Helpers\Code;
use App\Models\Common\DataScope;
use App\Models\Common\Menu;
use App\Models\Common\MenuAction;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class UserGroup extends BaseModel
{

    protected $table = 'user_groups';
    protected $fillable = ['title', 'description', 'abbreviation', 'data_scope'];
    public $params = ['title', 'abbreviation'];
    public $sorters = ['abbreviation', 'title', 'created_at'];

    public function users()
    {
        return $this->belongsToMany('App\Models\Account\User', 'user_group_map_user', 'group_id', 'user_id')->withTimestamps();
    }

    public function permissions()
    {
        return $this->belongsToMany('App\Models\Account\UserPermission', 'user_group_map_permission', 'group_id', 'permission_id');
    }

    public function menus()
    {
        return $this->belongsToMany('App\Models\Common\Menu', 'user_group_map_menu', 'group_id', 'menu_id');
    }
    
    public function actions()
    {
        return $this->belongsToMany('App\Models\Common\MenuAction', 'user_group_menu_actions', 'group_id', 'action_id');
    }

    public function addUsergroup($data)
    {
        $data['data_scope'] = $this->getDataScope();
        return $this->create($data);
    }

    public function deleteUsergroup($id)
    {
        $model = $this->with('users')->find($id);

        if (!$model) {
            return null;
        } else if ($model->users->count() > 0) {
            return Code::INSIDE_EXIST_DEPENDENCE;
        }

        return $model->delete();
    }

    public function editUsergroup($id, $data)
    {
        $model = $this->find($id);

        if (!$model) {
            return null;
        }

        return $model->updateOrCreate(['id' => $id], $data);
    }

    public function getUsergroupList($limit, $sorter, $search)
    {
        $perPage = $limit > 0 ? $limit : $this->limit;
        $model = $this->orderBy($sorter[0], $sorter[1]);
        $model->select(['id', 'abbreviation', 'title', 'description', 'created_at']);
        foreach ($search as $key => $value) {
            switch ($key) {
                case 'title':
                case 'abbreviation':
                    $model->where($key, 'like', '%' . $value . '%');
                    break;
            }
        }
        return $model->paginate($perPage)->toArray();
    }

    public function getUsergroupListAll()
    {
        return $this->all(['id', 'title'])->toArray();
//        return $this->where('id','!=', Code::SUPER_ADMIN_GROUP_ID)->get(['id', 'title'])->toArray();
    }

    public function getUsergroupUserList($id, $limit)
    {
        $model = $this->find($id);

        if (!$model) {
            return null;
        }

        $perPage = $limit > 0 ? $limit : $this->limit;

        return $model->users()->with('department:id,title')->paginate($perPage, ['users.id', 'username', 'gender', 'phone', 'job', 'data_scope', 'is_blocked', 'department_id'])->toArray();
    }

    public function getUsergroupPermissionList($id)
    {
        $model = $this->find($id);

        if (!$model) {
            return null;
        }

        $data = [];

        $permissions = $model->permissions->toArray();

        if ($permissions) {
            foreach ($permissions as $item) {
                $data[] = $item['id'] . '';
            }
        }

        return $data;
    }

    public function editUsergroupPermission($id, $data)
    {
        $model = $this->find($id);

        if (!$model) {
            return null;
        }

        $dataTotal = count($data);

        if ($dataTotal > 0) {
            $permission = UserPermission::whereIn('id', $data)->get()->toArray();

            if (count($permission) !== $dataTotal) {
                return Code::INSIDE_EXIST_DEPENDENCE;
            }
        }

        return $model->permissions()->sync($data);
    }

    public function getUsergroupMenuList($id)
    {
        $model = $this->find($id);

        if (!$model) {
            return null;
        }

        $data = [];

        $menus = $model->menus->toArray();

        if ($menus) {
            foreach ($menus as $item) {
                $data[] = $item['id'] . '';
            }
        }

        return $data;
    }

    public function editUsergroupMenu($id, $data)
    {
        $model = $this->find($id);

        if (!$model) {
            return null;
        }

        $dataTotal = count($data);

        if ($dataTotal > 0) {
            $menus = Menu::whereIn('id', $data)->get()->toArray();

            if (count($menus) !== $dataTotal) {
                return Code::INSIDE_EXIST_DEPENDENCE;
            }
        }

        return $model->menus()->sync($data);
    }

    public function getUsergroup($id)
    {
        $model = $this->find($id);

        if (!$model) {
            return null;
        }

        return $model->toArray();
    }

    public function getUsergroupPermissionAll($id)
    {
        $model = $this->find($id);

        if (!$model) {
            return null;
        }

        return $model->permissions()->get(['slug'])->toArray();
    }

    /**
     * 获取指定用户组下指定菜单的功能
     * @param $id
     * @param $menuId
     * @return \Illuminate\Database\Eloquent\Collection|static[]
     */
    public function getUsergroupMenuActionAll($id, $menuId)
    {
        //获取功能下数据域
        $data = UserGroupMenuActionScope::with(['scopes:id,title'])
            ->select(['action_id', 'scope_id'])
            ->where('group_id', $id)
            ->where('menu_id', $menuId)
            ->get()
            ->toArray();

        $actionScopeIds = array_unique(array_column($data, 'action_id'));

        //获取功能
        $actions = UserGroupMenuAction::select(['action_id'])->where('group_id', $id)->where('menu_id', $menuId)->get()->toArray();
        $actionIds = array_unique(array_column($actions, 'action_id'));

        //获取功能未添加数据域数据
        $diffAction = array_diff($actionIds, $actionScopeIds);

        $scope = [];
        foreach ($data as $k => $v) {
            $scopeInfo['value'] =  strval($v['scope_id']);
            $scopeInfo['label'] =  $v['scopes']['title'];
            $scope[$v['action_id']][] = $scopeInfo;
        }

        foreach ($diffAction as $diffKey => $diffValue) {
            $scope[$diffValue] = [];
        }

        return $scope;
    }

    /**
     * 编辑指定用户组下指定菜单的功能
     * @param $id
     * @param $menuId
     * @param $actions
     * @return bool|int|null
     */
    public function editUsergroupMenuAction($id, $menuId, $actions)
    {
        try {
            //判断用户组菜单关系是否存在
            $groupMenu = UserGroupMapMenu::where('menu_id', $menuId)->where('group_id', $id)->first(['id']);
            if (!$groupMenu) {
                return Code::INSIDE_ERROR_3;
            }

            //判断功能是否存在
            $actionIds = array_column($actions, 'action_id');
            $action = MenuAction::whereIn('id', $actionIds)->where('menu_id', $menuId)->count();

            if ($action !== count($actions)) {
                return Code::INSIDE_ERROR_1;
            }

            //判断数据域是否存在
            $scopeIds = array_values(array_unique(array_flatten(array_column($actions, 'scope_id'))));
            if (count($scopeIds) > 0) {
                $scope = DataScope::whereIn('id', $scopeIds)->count();

                if ($scope != count($scopeIds)) {
                    return Code::INSIDE_ERROR_1;
                }
            }

            DB::beginTransaction();
            $userGroupMenuAction['group_id'] = $id;
            $userGroupMenuAction['menu_id'] = $menuId;

            //获取已存在数据
            $groupActions = UserGroupMenuAction::where('group_id', $id)->where('menu_id', $menuId)->get(['action_id', 'id'])->toArray();
            $groupActionIds = array_column($groupActions, 'action_id');


            $menuAction = MenuAction::where('menu_id', $menuId)->find($actionIds, ['id']);
            if (!$menuAction) {
                return Code::INSIDE_ERROR_2;
            }

            $userGroupMenuAction['data_scope'] = Auth::user()->data_scope;
            foreach ($actions as $key => $value) {
                if (!in_array($value['action_id'], $groupActionIds)) {
                    $userGroupMenuAction['action_id'] = $value['action_id'];
                    UserGroupMenuAction::create($userGroupMenuAction);
                    if (count($value['scope_id']) > 0) {
                        $scopeRequestIds = array_unique($value['scope_id']);
                        foreach ($scopeRequestIds as $scopeKey => $scopeValue) {
                            $userGroupMenuAction['scope_id'] = $scopeValue;
                            UserGroupMenuActionScope::create($userGroupMenuAction);
                        }
                    }
                } else {
                    $userGroupMenuActionScope = UserGroupMenuActionScope::where('group_id', $id)->where('menu_id', $menuId)->where('action_id', $value['action_id'])->get(['scope_id'])->toArray();
                    $userGroupMenuActionScopeIds = array_column($userGroupMenuActionScope, 'scope_id');

                    $addUserGroupMenuActionScopeIds = array_unique(array_diff($value['scope_id'], $userGroupMenuActionScopeIds));

                    if (count($addUserGroupMenuActionScopeIds) > 0) {
                        $userGroupMenuAction['action_id'] = $value['action_id'];
                        foreach ($addUserGroupMenuActionScopeIds as $addKey => $addValue) {
                            $userGroupMenuAction['scope_id'] = $addValue;
                            UserGroupMenuActionScope::create($userGroupMenuAction);
                        }
                    }

                    $delUserGroupMenuActionScopeIds = array_unique(array_diff($userGroupMenuActionScopeIds, $value['scope_id']));

                    if (count($delUserGroupMenuActionScopeIds) > 0) {
                        foreach ($delUserGroupMenuActionScopeIds as $delScopeKey => $delScopeValue) {
                            UserGroupMenuActionScope::where('group_id', $id)->where('menu_id', $menuId)->where('action_id', $value['action_id'])->where('scope_id', $delScopeValue)->delete();
                        }
                    }
                }
            }

            $del = array_unique(array_diff($groupActionIds, $actionIds));
            if (count($del) > 0) {
                $ids = [];
                foreach ($groupActions as $delKey => $delValue) {
                    if (in_array($delValue['action_id'], $del)) {
                        $ids[] = $delValue['id'];
                    }
                }
                UserGroupMenuAction::whereIn('id', $ids)->delete();
                UserGroupMenuActionScope::where('group_id', $id)->where('menu_id', $menuId)->whereIn('action_id', $ids)->delete();
            }

            DB::commit();
            return Code::INSIDE_TRUE;
        } catch (\Exception $e) {
            DB::rollBack();
            return $this->throwError($e);
        }
    }

    /**
     * 获取指定用户组下菜单
     * @param $id
     * @return null
     */
    public function getUsergroupMenuSelected($id)
    {
        $model = $this->find($id);

        if (!$model) {
            return null;
        }

        $data = $model->menus()->get(['menus.id', 'name', 'parent_id'])->toArray();

        $menus = [];
        foreach ($data as $key => $value) {
            if (!isset($value['parent_id'])) {
                $menus[$value['id']]['name'] = $value['name'];
                $menus[$value['id']]['id'] = $value['id'];
                unset ($data[$key]);
                $child = [];
                foreach ($data as $childKey => $childValue) {
                    if ($childValue['parent_id'] === $value['id']) {
                        $child[$childValue['id']]['name'] = $childValue['name'];
                        $child[$childValue['id']]['id'] = $childValue['id'];
                    }
                }
                $menus[$value['id']]['children'] = array_values($child);
            }
        }

        return array_values($menus);
    }

}
